package com.kingmed.kmss.gateway.config.sa;

import cn.dev33.satoken.reactor.context.SaReactorSyncHolder;
import cn.dev33.satoken.reactor.filter.SaReactorFilter;
import cn.dev33.satoken.router.SaRouter;
import cn.dev33.satoken.stp.StpUtil;
import cn.dev33.satoken.util.SaResult;
import cn.hutool.http.HttpStatus;
import com.kingmed.kmss.gateway.filter.OpenUrlAuthFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.server.ServerWebExchange;

import java.util.Collections;
import java.util.List;

@Configuration
public class SaTokenConfig {

    @Autowired
    private IgnoredUrlConfig ignoredUrlConfig;
    @Autowired
    private OpenUrlAuthFilter openUrlAuthFilter;

    /** 对外开放接口校验开关,默认false **/
    @Value("${open-url-check.enable:false}")
    private boolean openUrlAuthStatus;

    /**
     * 注册Sa-Token全局过滤器
     */
    @Bean
    public SaReactorFilter getSaReactorFilter() {
        List<String> ignoreUrls = ignoredUrlConfig.getUrls();
        return new SaReactorFilter()
                // 拦截地址
                .addInclude("/**")
                // 开放地址
                .addExclude("/favicon.ico")
                // 除ignoreUrls其他都需要认证
                .setExcludeList(ignoreUrls)
                // 鉴权方法：每次访问进入
                .setAuth(r -> {

                    // 校验是否外部系统调用对外接口
                    if (openUrlAuthStatus && openUrlAuthFilter.check()){
                        return;
                    }

                    // 检查token是否有效
                    StpUtil.checkLogin();

                    // 登录认证：除ignoreUrls,其他都需要认证(提供token)
                    SaRouter.match(Collections.singletonList("/**"), ignoreUrls, StpUtil::checkLogin);
                    // 权限认证：不同接口访问权限不同
                    //SaRouter.match("/blank-service/test/hello", () -> StpUtil.checkPermission("/aaa/**"));

                })
                // setAuth方法异常处理
                .setError(e -> {
                    // 设置错误返回格式为JSON
                    ServerWebExchange exchange = SaReactorSyncHolder.getContent();
                    exchange.getResponse().getHeaders().set("Content-Type", "application/json; charset=utf-8");
                    SaResult result =  SaResult.error(e.getMessage());
                    result.setCode(HttpStatus.HTTP_UNAUTHORIZED);
                    result.setMsg("会话已失效，请重新登录！");
                    return result;
                });
    }
}

